home *** CD-ROM | disk | FTP | other *** search
- /* ----------------------------------------------------------------
- * FILE
- * result.c
- *
- * DESCRIPTION
- * support for constant nodes needing special code.
- *
- * Example: in constant queries where no relations are scanned,
- * the planner generates result nodes. Examples of such queries are:
- *
- * retrieve (x = 1)
- * and
- * append emp (name = "mike", salary = 15000)
- *
- * Result nodes are also used to optimise queries
- * with tautological qualifications like:
- *
- * retrieve (emp.all) where 2 > 1
- *
- * In this case, the plan generated is
- *
- * Result (with 2 > 1 qual)
- * /
- * SeqScan (emp.all)
- *
- * INTERFACE ROUTINES
- * ExecResult - fetch a tuple from the node
- * ExecInitResult - initialize the node
- * ExecEndResult - shutdown the node
- *
- * NOTES
- *
- *
- * IDENTIFICATION
- * $Header: /private/postgres/src/executor/RCS/n_result.c,v 1.5 1992/08/04 17:38:00 mer Exp $
- * ----------------------------------------------------------------
- */
-
- #include "executor/executor.h"
-
- RcsId("$Header: /private/postgres/src/executor/RCS/n_result.c,v 1.5 1992/08/04 17:38:00 mer Exp $");
-
- /* ----------------------------------------------------------------
- * ExecResult(node)
- *
- * returns the tuples from the outer plan which satisify the
- * qualification clause. Since result nodes with right
- * subtrees are never planned, we ignore the right subtree
- * entirely (for now).. -cim 10/7/89
- *
- * old comments:
- * Returns the tuple joined from inner and outer tuples which
- * satisfies the qualification clause.
- *
- * It scans the inner relation to join with current outer tuple.
- *
- * If none is found, next tuple form the outer relation
- * is retrieved and the inner relation is scanned from the
- * beginning again to join with the outer tuple.
- *
- * Nil is returned if all the remaining outer tuples are tried and
- * all fail to join with the inner tuples.
- *
- * If inner subtree is not present, only outer subtree is processed.
- *
- * Also, the qualification containing only constant clauses are
- * checked first before any processing is done. It always returns
- * 'nil' if the constant qualification is not satisfied.
- * ----------------------------------------------------------------
- */
- /**** xxref:
- * ExecProcNode
- * ExecResult
- ****/
- TupleTableSlot
- ExecResult(node)
- Result node;
- {
- ResultState resstate;
- TupleTableSlot outerTupleSlot;
- TupleTableSlot resultSlot;
- Plan outerPlan;
- TupleDescriptor outerType;
- Buffer outerBuffer;
-
- TupleDescriptor tupType;
- Pointer tupValue;
- List targetList;
- int len;
- ExprContext econtext;
- List qual;
- bool qualResult;
- bool isDone;
- int resloop;
-
- /* ----------------
- * initialize the result node's state
- * ----------------
- */
- resstate = get_resstate(node);
-
- /* ----------------
- * get the expression context
- * ----------------
- */
- econtext = get_cs_ExprContext((CommonState) resstate);
-
- /* ----------------
- * check tautological qualifications like (2 > 1)
- * ----------------
- */
- qual = get_resconstantqual(node);
- if (! lispNullp(qual)) {
- qualResult = ExecQual(qual, econtext);
- /* ----------------
- * if we failed the constant qual, then there
- * is no need to continue processing because regardless of
- * what happens, the constant qual will be false..
- * ----------------
- */
- if (qualResult == false)
- return NULL;
-
- /* ----------------
- * our constant qualification succeeded so now we
- * throw away the qual because we know it will always
- * succeed.
- * ----------------
- */
- set_resconstantqual(node, LispNil);
- }
-
- if (get_cs_TupFromTlist((CommonState) resstate)) {
- ProjectionInfo projInfo;
-
- projInfo = get_cs_ProjInfo((CommonState)resstate);
- resultSlot = ExecProject(projInfo, &isDone);
- if (!isDone)
- return resultSlot;
- }
- /* ----------------
- * retrieve tuples from the outer plan until there are no more.
- * ----------------
- */
- for(;;) {
- /* ----------------
- * if (resloop == 1) then it means that we were asked to return
- * a constant tuple and we alread did the last time ExecResult()
- * was called, so now we are through.
- * ----------------
- */
- resloop = get_rs_Loop(resstate);
- if (resloop == 1)
- return NULL;
-
- /* ----------------
- * get next outer tuple if necessary.
- * ----------------
- */
- outerPlan = (Plan) get_outerPlan((Plan) node);
-
- if (outerPlan != NULL) {
- outerTupleSlot = ExecProcNode(outerPlan);
-
- if (TupIsNull((Pointer) outerTupleSlot))
- return NULL;
-
- set_cs_OuterTupleSlot((CommonState) resstate, outerTupleSlot);
- }
-
- /* ----------------
- * get the information to place into the expr context
- * ----------------
- */
- qual = get_resrellevelqual(node);
- resstate = get_resstate(node);
- outerPlan = (Plan) get_outerPlan((Plan) node);
-
- outerTupleSlot = get_cs_OuterTupleSlot((CommonState)resstate);
-
- /* ----------------
- * fill in the information in the expression context
- * XXX gross hack. use outer tuple as scan tuple
- * ----------------
- */
- set_ecxt_outertuple(econtext, outerTupleSlot);
- set_ecxt_scantuple(econtext, outerTupleSlot);
-
- /* ----------------
- * if we don't have an outer plan, then it's probably
- * the case that we are doing a retrieve or an append
- * with a constant target list, so we should only return
- * the constant tuple once or never if we fail the qual.
- * ----------------
- */
- if (outerPlan == NULL)
- set_rs_Loop(resstate, 1);
-
- /* ----------------
- * test qualification
- * ----------------
- */
- qualResult = ExecQual(qual, econtext);
-
- if (qualResult == true) {
- /* ----------------
- * qualification passed, form the result tuple and
- * pass it back using ExecProject()
- * ----------------
- */
- ProjectionInfo projInfo;
-
- projInfo = get_cs_ProjInfo((CommonState)resstate);
- resultSlot = ExecProject(projInfo, &isDone);
- set_cs_TupFromTlist((CommonState) resstate, !isDone);
- return resultSlot;
- }
- }
- }
-
- /* ----------------------------------------------------------------
- * ExecInitResult
- *
- * Creates the run-time state information for the nestloop node
- * produced by the planner and initailizes inner and outer relations
- * (child nodes).
- * ----------------------------------------------------------------
- */
- /**** xxref:
- * ExecInitNode
- ****/
- List
- ExecInitResult(node, estate, parent)
- Plan node;
- EState estate;
- Plan parent;
- {
- ResultState resstate;
- TupleDescriptor tupType;
- Pointer tupValue;
- List targetList;
- int len;
- ParamListInfo paraminfo;
- ExprContext econtext;
- int baseid;
-
- /* ----------------
- * assign execution state to node
- * ----------------
- */
- set_state( node, (EStatePtr)estate);
-
- /* ----------------
- * create new ResultState for node
- * ----------------
- */
- resstate = MakeResultState(0);
- set_resstate((Result) node, resstate);
-
- /* ----------------
- * Miscellanious initialization
- *
- * + assign node's base_id
- * + assign debugging hooks and
- * + create expression context for node
- * ----------------
- */
- ExecAssignNodeBaseInfo(estate, (BaseNode) resstate, parent);
- ExecAssignDebugHooks( node, (BaseNode) resstate);
- ExecAssignExprContext(estate, (CommonState) resstate);
-
- #define RESULT_NSLOTS 1
- /* ----------------
- * tuple table initialization
- * ----------------
- */
- ExecInitResultTupleSlot(estate, (CommonState) resstate);
-
- /* ----------------
- * then initialize children
- * ----------------
- */
- ExecInitNode((Plan) get_outerPlan(node), estate, node);
- ExecInitNode((Plan) get_innerPlan(node), estate, node);
-
- /* ----------------
- * initialize tuple type and projection info
- * ----------------
- */
- ExecAssignResultTypeFromTL(node, (CommonState)resstate);
- ExecAssignProjectionInfo(node, (CommonState) resstate);
-
- /* ----------------
- * set "are we done yet" to false
- * ----------------
- */
- set_rs_Loop(resstate, 0);
-
- return LispTrue;
- }
-
- int
- ExecCountSlotsResult(node)
- Plan node;
- {
- return ExecCountSlotsNode(get_outerPlan(node)) +
- ExecCountSlotsNode(get_innerPlan(node)) +
- RESULT_NSLOTS;
- }
-
- /* ----------------------------------------------------------------
- * ExecEndResult
- *
- * fees up storage allocated through C routines
- * ----------------------------------------------------------------
- */
- /**** xxref:
- * ExecEndNode
- ****/
- void
- ExecEndResult(node)
- Result node;
- {
- ResultState resstate;
- Pointer tupValue;
-
- resstate = get_resstate(node);
-
- /* ----------------
- * Free the projection info
- *
- * Note: we don't ExecFreeResultType(resstate)
- * because the rule manager depends on the tupType
- * returned by ExecMain(). So for now, this
- * is freed at end-transaction time. -cim 6/2/91
- * ----------------
- */
- ExecFreeProjectionInfo((CommonState)resstate);
-
- /* ----------------
- * shut down subplans
- * ----------------
- */
- ExecEndNode((Plan) get_outerPlan((Plan)node));
- ExecEndNode((Plan) get_innerPlan((Plan)node));
-
- /* ----------------
- * clean out the tuple table
- * ----------------
- */
- ExecClearTuple((Pointer)get_cs_ResultTupleSlot((CommonState)resstate));
- }
-